package com.bodgittandscarper.broker.server;

import static java.util.logging.Level.SEVERE;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.swing.SwingUtilities;

import suncertify.db.Data;

import com.bodgittandscarper.broker.client.BrokerClient;
import com.bodgittandscarper.broker.client.BrokerClientImpl;
import com.bodgittandscarper.broker.types.ModeFlag;

/**
 * 
 * Main control class for the Server application. When the Server is started, a 
 * {@link com.bodgittandscarper.broker.server.ServerStartupDialog} is shown. 
 * The dialog handles access to a specified property which is used to store the location of the database file.
 * When a correct location is set by the user, the database is initialized and last it instantiates the RMI boundary 
 * class. The boundary class is registered with the RMI registry.
 * <p>
 * If the application is started in alone mode, the boundary class is not registered with the RMI registry.
 * <p>
 * The Server class exits the JVM(<code>System.exit(-1)</code>) in the following cases:
 * <ul> 
 * <li>If a <code>FileNotFoundException</code> is thrown when the database is instantiated.</li>
 * <li>If the Database is corrupted and cannot be initialized.</li>
 * <li>If the Server is stated in server mode <b>and</b> an exception is thrown when it is registered with the RMI registry.</li>
 * </ul>
 * @author Morten Rummelhoff
 *
 */
public class Server {

	private Logger log = Logger.getLogger(getClass().getName());

	private static BrokerClient brokerClient;
	private ServerStartupDialog serverDialog;

	
	/**
	 * String defining the name of the registered RMI service.
	 */
	public static final String RMI_SERVICE_NAME = "BodgittScarperRMIService";

	/**
	 * Sole Constructor for the Server class. Starting mode of the Server is specified with a ModeFlag.
	 * 
	 * @param modeFlag - mode, that specifies how the Server is started. The mode can be server or alone. If mode is server, the 
	 * boundary class is registered with the RMI registry. Alone mode, the boundary class is only initialized.
	 */
	public Server(ModeFlag modeFlag) {

		if (log.isLoggable(Level.INFO))
			log.log(Level.INFO, "Starting BrokerServer");


		try {
			SwingUtilities.invokeAndWait(new Runnable() {
					
				@Override
				public void run() {
					serverDialog = new ServerStartupDialog();
					serverDialog.setVisible(true);

				}
			});
		} catch (Exception e) {
			e.printStackTrace();
		} 

		Database database = null;
		Data data = null;
		try {
			database = new Database(serverDialog.getDBFile());
			data = new Data(database);
		} catch (FileNotFoundException e) {
			if (log.isLoggable(SEVERE)) {
				log.log(SEVERE, "Unable to start database.", e);
			}
			System.exit(-1);
		}  catch (IOException e) {
			if (log.isLoggable(SEVERE)) {
				log.log(SEVERE, "Unable to read database.", e);
			}
			System.exit(-1);
		}


		brokerClient = new BrokerClientImpl(data);

		//Here check if Alone, then dont put up a RMI service
		if (modeFlag == ModeFlag.ALONE) {
			return;
		}

		try {
			BrokerClient stub =
				(BrokerClient) UnicastRemoteObject.exportObject(brokerClient, 0);

			Registry registry = LocateRegistry.createRegistry(1099);
			registry.rebind(RMI_SERVICE_NAME, stub);

			if (log.isLoggable(Level.INFO))
				log.log(Level.INFO, "BrokerServer RMI service bound");

		} catch (RemoteException e) {
			if (log.isLoggable(SEVERE)) {
				log.log(SEVERE, "Unable to register RMI service.", e);
			}

			System.exit(-1);
		}

	}
	/**
	 * Gets the initialized <code>BrokerClient</code>. The client class is used for communication to the Server Application. 
	 * The boundary class can be registered with a RMI registry depending on the <code>ModeFlag</code> 
	 * when the <code>Server</code> class is started. 
	 * 
	 * @return boundary class which can be used by clients 
	 */
	public BrokerClient getBrokerClient() {
		return brokerClient;
	}


}
